#ifndef __PANEL_WAH_H__
#define __PANEL_WAH_H__

#include <wx/wx.h>
#include <wx/aui/aui.h>
#include <wx/wrapsizer.h>
#include <wx/event.h>
#include <wx/xml/xml.h>
#include "MyCommon.h"

class MyEventWah : public wxCommandEvent {
public:
    MyEventWah(wxEventType eventType = wxEVT_NULL,int id = 0)
        : wxCommandEvent(eventType, id) {

        }

    // 克隆事件对象
//    [[nodiscard]] // C++17 才支持，意思就是函数返回值不能被忽略，否则编译器发出警告
    virtual wxEvent *Clone() const override {
        return new MyEventWah(*this);
    }

    void SetFilterFreqWidth(double filter_freq_width) {
        m_filter_freq_width = filter_freq_width;
    }
    void SetSpeed(double speed) {
        m_speed = speed;
    }
    void SetFilterQ(double q) {
        m_filter_q = q;
    }
    void SetFilterGain(double gain) {
        m_filter_gain = gain;
    }
    void SetFilterFreqCenter(double filter_freq_center) {
        m_filter_freq_center = filter_freq_center;
    }
    void SetEnable(bool enable) {
        this->enable = enable;
    }
    double GetFilterFreqWidth() {
        return m_filter_freq_width;
    }
    double GetSpeed() {
        return m_speed;
    }
    double GetFilterQ() {
        return m_filter_q;
    }
    double GetFilterGain() {
        return m_filter_gain;
    }
    double GetFilterFreqCenter() {
        return m_filter_freq_center;
    }
    bool GetEnable() {
        return enable;
    }
    void SetPresetIndex(const unsigned int index) {
        preset_index = index;
    }
    int GetPresetIndex() {
        return preset_index;
    }

private:

    double m_speed;
    double m_filter_q;
    double m_filter_gain;
    double m_filter_freq_center;
    double m_filter_freq_width;
    bool enable;
    int preset_index;
};

wxDECLARE_EVENT(myEVT_WAH, MyEventWah);
wxDECLARE_EVENT(myEVT_WAH_FILTER_FREQ_WIDTH, MyEventWah);
wxDECLARE_EVENT(myEVT_WAH_SPEED, MyEventWah);
wxDECLARE_EVENT(myEVT_WAH_FILTER_Q, MyEventWah);
wxDECLARE_EVENT(myEVT_WAH_FILTER_GAIN, MyEventWah);
wxDECLARE_EVENT(myEVT_WAH_FILTER_FREQ_CENTER, MyEventWah);
wxDECLARE_EVENT(myEVT_WAH_ENABLE, MyEventWah);

typedef void (wxEvtHandler::*MyWahEventFunction)(MyEventWah &);

#define MyWahEventHandler(func) \
    wxEVENT_HANDLER_CAST(MyWahEventFunction, func)

#define M_EVT_WAH(id, fn) \
    wx__DECLARE_EVT1(myEVT_WAH, id, MyWahEventHandler(fn))
#define M_EVT_WAH_FILTER_FREQ_WIDTH(id, fn) \
    wx__DECLARE_EVT1(myEVT_WAH_FILTER_FREQ_WIDTH, id, MyWahEventHandler(fn))
#define M_EVT_WAH_SPEED(id, fn) \
    wx__DECLARE_EVT1(myEVT_WAH_SPEED, id, MyWahEventHandler(fn))
#define M_EVT_WAH_FILTER_Q(id, fn) \
    wx__DECLARE_EVT1(myEVT_WAH_FILTER_Q, id, MyWahEventHandler(fn))
#define M_EVT_WAH_FILTER_GAIN(id, fn) \
    wx__DECLARE_EVT1(myEVT_WAH_FILTER_GAIN, id, MyWahEventHandler(fn))
#define M_EVT_WAH_FILTER_FREQ_CENTER(id, fn) \
    wx__DECLARE_EVT1(myEVT_WAH_FILTER_FREQ_CENTER, id, MyWahEventHandler(fn))
#define M_EVT_WAH_ENABLE(id, fn) \
    wx__DECLARE_EVT1(myEVT_WAH_ENABLE, id, MyWahEventHandler(fn))

class PanelWah : public wxPanel
{
public:
    PanelWah(const wxString &title, wxXmlNode *node, wxWindowID id = wxID_ANY, wxWindow *parent = nullptr);
    typedef struct
    {
        bool enable;
        float speed;
        float filter_freq_center;
        float filter_freq_width;
        float filter_q;
        float filter_gain;
    }param_struct;

private:

    enum{
        EV_ENABLE = 1,
        EV_SPEED,
        EV_FILTER_Q,
        EV_FILTER_GAIN,
        EV_FILTER_FREQ_CENTER,
        EV_FILTER_FREQ_WIDTH,
    };

    const double speed_max = 1;
    const double speed_min = 0;
    const double speed_step = 0.1;
    const double filter_q_max = 5;
    const double filter_q_min = 0.1;
    const double filter_q_step = 0.01;
    const double filter_gain_max = 30;
    const double filter_gain_min = 0;
    const double filter_gain_step = 0.01;
    const double filter_freq_center_max = 2000;
    const double filter_freq_center_min = 100;
    const double filter_freq_center_step = 10;
    const double filter_freq_width_max = 1000;
    const double filter_freq_width_min = 100;
    const double filter_freq_width_step = 10;

    const char *attr_name_select = "select";
    const char *attr_name_preset_default = "default";
    const char *attr_name_param_enable = "enable";
    const char *attr_name_param_speed = "speed";
    const char *attr_name_param_filter_q = "filter_q";
    const char *attr_name_param_filter_gain = "filter_gain";
    const char *attr_name_param_filter_freq_center = "filter_freq_center";
    const char *attr_name_param_filter_freq_width = "filter_freq_width";

    wxWindowID ID_TXT_SPEED;
    wxWindowID ID_TXT_FILTER_Q;
    wxWindowID ID_TXT_FILTER_GAIN;
    wxWindowID ID_TXT_FILTER_FREQ_CENTER;
    wxWindowID ID_TXT_FILTER_FREQ_WIDTH;
    wxWindowID ID_SLI_SPEED;
    wxWindowID ID_SLI_FILTER_Q;
    wxWindowID ID_SLI_FILTER_GAIN;
    wxWindowID ID_SLI_FILTER_FREQ_CENTER;
    wxWindowID ID_SLI_FILTER_FREQ_WIDTH;
    wxWindowID ID_CHK_SWITCH;
    wxWindowID ID_CHO_PRESET;


    wxAuiPaneInfo paneInfo;
    MyEventWah param_event;
    param_struct param;
    wxXmlNode *root_node;
    wxXmlNode *preset_node;
    int select_index;

public:
    wxAuiPaneInfo &GetPaneInfo();
    void SetShow(bool show);
    double SetParamSpeed(double value);
    double SetParamFilterQ(double value);
    double SetParamFilterGain(double value);
    double SetParamFilterFreqCenter(double value);
    double SetParamFilterFreqWidth(double value);
    bool SetParamEnable(bool value);;
    double GetParamSpeed();
    double GetParamFilterQ();
    double GetParamFilterGain();
    double GetParamFilterFreqCenter();
    double GetParamFilterFreqWidth();
    bool GetParamEnable();
    void SetPresetIndex(const unsigned int index);
    int GetPresetIndex();
    void PresetListClear(void);
    void AddPresetList(const wxString &preset_name);
    wxXmlNode *SaveCurrentParamsToNewPreset(wxXmlNode *root, const wxString &new_preset_name,int &is_same);
    wxXmlNode *WriteToXML(wxXmlNode *node);

private:
    void OnSliderChange(wxCommandEvent& event);
    void OnTextEnter(wxCommandEvent& event);
    void OnChkChange(wxCommandEvent& event);
    void OnCombChange(wxCommandEvent& event);

    void TrigerEvent(int ev);
    wxXmlNode *SelectPreset(wxString name);

    // wxDECLARE_EVENT_TABLE();
};


#endif
